﻿using System.Collections.Generic;
using System.Windows;

namespace Model
{
	public class Trajectory
	{
		private int timeStamp;
		private double fieldLength;

		/// <summary>
		/// Gibt den aktuellen Schritt der Simulation zurück.
		/// </summary>
		public int TimeStamp
		{
			get { return timeStamp; }
		}

		private Dictionary<CellDefinition, List<double>> tLines;

		/// <summary>
		/// Initialisiert die Trajektorie mit allen Zelldefinitionen, die in Environment vorhanden sind.
		/// </summary>
		public void Initialize()
		{
			this.timeStamp = 0;
			tLines = new Dictionary<CellDefinition, List<double>>();
			foreach (var cd in Environment.CellDefinitions.Values)
			{
				tLines.Add(cd, new List<double>());
				tLines[cd].Add(0);
			}
			fieldLength = Environment.Cells.GetLength(0) * Environment.Cells.GetLength(1);
		}

		public List<double> this[CellDefinition key]
		{
			get { return tLines[key]; }
		}

		public List<double> this[string key]
		{
			get { return tLines[new CellDefinition(key)]; }
		}

		/// <summary>
		/// Fügt dem aktuellen Zeitschritt der Trajektorie eine weitere Zelle der Definition hinzu.
		/// </summary>
		/// <param name="cellDefinition"></param>
		/// <param name="value"></param>
		public void AddToCurrentValue(CellDefinition cellDefinition)
		{
			tLines[cellDefinition][timeStamp]++;
		}

		/// <summary>
		/// Gibt den aktuellen Wert für die übergebene Zelldefinition zurück.
		/// </summary>
		/// <param name="cellDefinition"></param>
		/// <returns></returns>
		public double GetCurrentValue(CellDefinition cellDefinition)
		{
			return this.tLines[cellDefinition][timeStamp];
		}

		/// <summary>
		/// Gibt den aktuellen Wert für die übergebene Zelldefinition zurück.
		/// </summary>
		/// <param name="cellDefinitionName"></param>
		/// <returns></returns>
		public double GetCurrentValue(string cellDefinitionName)
		{
			return this.tLines[new CellDefinition(cellDefinitionName)][timeStamp];
		}

		/// <summary>
		/// Bereitet die Trajektorie auf den nächsten Schritt der Simulation vor.
		/// </summary>
		public void PrepareNextStep()
		{
			foreach (var list in tLines.Values)
			{
				list[timeStamp] /= fieldLength;
				list.Add(0);
			}
			OnNextStep();
			timeStamp++;
		}

		#region OnNextStep
		public delegate void NextStepEventHandler(object sender, TrajectoryChangedEventArgs e);

		public event NextStepEventHandler NextStep;

		protected void OnNextStep()
		{
			if (NextStep != null)
			{
				Dictionary<CellDefinition, Point> values = new Dictionary<CellDefinition, Point>();
				foreach (var cd in tLines)
				{
					values.Add(cd.Key, new Point(timeStamp, cd.Value[timeStamp]));
				}
				TrajectoryChangedEventArgs e = new TrajectoryChangedEventArgs() { CurrentPoints = values };
				NextStep(this, e);
			}
		}
		#endregion

	}
}
